iT邦幫忙

2023 iThome 鐵人賽

DAY 17
0
AI & Data

已 django + channels 來取得即時股價資料的推播系列 第 17

[Day 17] 實戰應用 - 查詢商品資料(下)

  • 分享至 

  • xImage
  •  

必要條件

聊天室範例要能做到[Day 08] - [Day 10]

1.登入聊天室後,需要告訴遊客規格

# chat/consumers.py
...
def connect(self):
    self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
    self.room_group_name = f"chat_{self.room_name}"


    # Join room group
    async_to_sync(self.channel_layer.group_add)(
        self.room_group_name, self.channel_name
    )

    self.accept()

    message = f"""
歡迎來到 {self.room_name} 股票聊天室,
查詢上市清單請按 1
查詢上櫃清單請按 2
查詢商品詳細名單請輸入商品代碼
        """
    async_to_sync(self.channel_layer.group_send)(
        self.room_group_name, {"type": "chat.message", "message": message}
    )
...

設計上在遊客進來時發送 message, 所以在 connect (連接上的時候) 傳送訊息至 Group = 'chat_[room_name]'
且指定接收者為 chat_message 這個 Func, 為啥是 chat_message 這個字眼呢? 因為前面有指定名稱為 "type": "chat.message", 這裡會轉換成 chat_message 來接收, 如下所示

# chat/consumers.py
...
# Receive message from room group
def chat_message(self, event):
    message = event["message"]

    # Send message to WebSocket
    self.send(text_data=json.dumps({"message": message}))

預期改完後
https://ithelp.ithome.com.tw/upload/images/20230924/20162724Qe2W00oNxj.png

接下來加入 Fugle API

# chat/consumers.py
import json

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer

from fugle_marketdata import RestClient

api_key = 'YOUR_API_KEY'
#

class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
        self.room_group_name = f"chat_{self.room_name}"
        client = RestClient(api_key=api_key)
        self.stock = client.stock

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name, self.channel_name
        )

        self.accept()

        message = f"""
歡迎來到 {self.room_name} 股票聊天室,
查詢上市清單請按 1
查詢上櫃清單請按 2
查詢商品詳細名單請輸入商品代碼
            """
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {"type": "chat.message", "message": message}
        )

    def disconnect(self, close_code):
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name, self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]
        if message == '1':
            data = self.stock.intraday.tickers(type='EQUITY', exchange="TWSE", isNormal=True)
            message = f'日期: {data["date"]}\n'
            for i in data['data']:
                if len(i["symbol"]) == 4:
                    message += f'代碼: {i["symbol"]}, 名稱: {i["name"]}\n'
        elif message == '2':
            data = self.stock.intraday.tickers(type='EQUITY', exchange="TPEx", isNormal=True)
            message = f'日期: {data["date"]}\n'
            for i in data['data']:
                if len(i["symbol"]) == 4:
                    message += f'代碼: {i["symbol"]}, 名稱: {i["name"]}\n'
        elif message.isdigit():
            msg = ''
            data = self.stock.intraday.ticker(symbol=message)
            for k, v in data.items():
                msg += f'{k}: {v}\n'
            message = msg
        else:
            message = '查詢失敗,請重新輸入條件'

        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name, {"type": "chat.message", "message": message}
        )

    # Receive message from room group
    def chat_message(self, event):
        message = event["message"]

        # Send message to WebSocket
        self.send(text_data=json.dumps({"message": message}))

我們可以透過幾個關鍵條件讓程式知道要查什麼.
然後依照條件回傳結果

# chat/consumers.py
def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json["message"]
        if message == '1':
            data = self.stock.intraday.tickers(type='EQUITY', exchange="TWSE", isNormal=True)
            message = f'日期: {data["date"]}\n'
            for i in data['data']:
                if len(i["symbol"]) == 4:
                    message += f'代碼: {i["symbol"]}, 名稱: {i["name"]}\n'

在 receive 接收到訊息,判斷訊息內容分別查詢不同的內容
哪為什麼這裡要額外判斷 symbol 長度等於 4 呢??
https://ithelp.ithome.com.tw/upload/images/20230924/20162724NvKy2yMwAs.png

有觀察到什麼嗎?

觀察到 怪怪的代碼!!
就是因為這個所以才會特別做一個篩選條件來排除!!!

預期輸入 1 會顯示
https://ithelp.ithome.com.tw/upload/images/20230924/20162724N0uRhxeMIH.png

預期輸入 2330 會顯示
https://ithelp.ithome.com.tw/upload/images/20230924/20162724L2Tyiur6xW.png

完成

牛刀小試

  • 查詢上櫃注意股票清單
  • 查詢上市暫停交易股票

參考

fugle-metadata
fugle 官方文件


上一篇
[Day 16] 實戰應用 - 查詢商品資料(上)
下一篇
[Day 18] 實戰應用 - 查詢盤後資料(上)
系列文
已 django + channels 來取得即時股價資料的推播30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言